#include "analyzebmp.h"
#include "QDebug"
AnalyzeBmp::AnalyzeBmp(ByteArrayList *l)
{
    this->source = l;
    this->quad = nullptr;
    this->targetData = new QByteArray;
    _init();
    //_readBytes();
}

AnalyzeBmp::~AnalyzeBmp(){
    _clean();
}

int AnalyzeBmp::getMaxBit(){
//    int quadSize = 0;
//    if(this->quad == nullptr){
//        quadSize = 0;
//    }else {
//        quadSize = sizeof (RGBQUAD);
//    }
//    return this->fileHeader.bfSize
//            - sizeof (BITMAPFILEHEADER)
//            - sizeof (BITMAPINFOHEADER)
//            - quadSize;
    //上述代码故意加入无用信息会导致数据有问题
    return this->fileHeader.bfSize - this->fileHeader.bfOffBits;
}

int AnalyzeBmp::getMaxByte(){
    return getMaxBit()/8;// - RESERVED_BYTES;   //用2个字节来表示插入多少字节的数据
}

int AnalyzeBmp::getType_biBitCount(){
    return this->infoHeader.biBitCount;
}

int AnalyzeBmp::getHeight(){
    return  this->infoHeader.biHeight;
}

int AnalyzeBmp::getWidth(){
    return  this->infoHeader.biWidth;
}

int AnalyzeBmp::getDataPtr(){
    return this->dataPtr;
}

ByteArrayList *AnalyzeBmp::getSourceList(){
    return this->source;
}

BITMAPFILEHEADER AnalyzeBmp::getFileHeader(){
    return this->fileHeader;
}

BITMAPINFOHEADER AnalyzeBmp::getInfoHeader(){
    return this->infoHeader;
}

RGBQUAD *AnalyzeBmp::getQuad(){
    return this->quad;
}

QByteArray * AnalyzeBmp::getTargetData(){
    return this->targetData;
}

bool AnalyzeBmp::writeMsg(QString s){
    int size = s.size();
//    if((size + RESERVED_BYTES)*8 > this->getMaxBit()){    //弃用
//        return false;
//    }
    if(size*8 > this->getMaxBit()){
        return false;
    }
//    //写入头部    //废弃，不需要插入数据的长度
//    BYTE reserved0 = size >> 8;
//    BYTE reserved1 = size;
//    _write(reserved0);
//    _write(reserved1);
    //写入数据
    for(int i = 0;i < size;i++){
//        BYTE a = s.at(i).unicode();
//        ushort b = s.at(i).unicode();
        _write(s.at(i).unicode());
    }

    return true;
}

QString AnalyzeBmp::readMsg(){
    //int size = NULL;
    QString target = "";
//    BYTE reserved0, reserved1;    //不必读取保留字了
//    reserved0 = _read();
//    reserved1 = _read();
//    size = (reserved0 << 8) | reserved1;
//    if(size > this->getMaxByte()){   //致命错误：读取得到的字节数大于文件能够写入的字节数
//        return NULL;
//    }

    for(int i = 0;i < this->getMaxByte();i++){
        if(this->dataPtr >= (int)this->getFileHeader().bfSize){
            break;
        }
        BYTE r = _read();
        if(r == 0x00000000){
            break;
        }
        target += (char)r;

    }

    return target;
}

BYTE AnalyzeBmp::_read(){
    int maxSizeEachArray = this->source->getMaxSizeEachArray();
    int indexOfArray, indexOfByte, a;
    char c;
    BYTE b = NULL;
    for(int i = 0;i < (int)sizeof(BYTE)*8;i++){
        indexOfArray = this->dataPtr / maxSizeEachArray;
        indexOfByte = this->dataPtr % maxSizeEachArray;
        c = this->source->at(indexOfArray).at(indexOfByte);
        a = GET_BYTE(c,7);
        (a == 1) ? SET_BYTE(b,i):CLR_BYTE(b,i);
        this->dataPtr ++;

        if(this->dataPtr == (int)this->getFileHeader().bfSize   //已经读取到最后
           && i != ((int)sizeof(BYTE)*8 - 1)){                  //并且字节没有读取到最后
            //致命错误
            return NULL;
        }
    }
    return b;
}

void AnalyzeBmp::_write(BYTE b){
    int maxSizeEachArray = this->source->getMaxSizeEachArray();
    int indexOfArray, indexOfByte, a;
    char c;
    for(int i = 0;i < (int)sizeof(b)*8;i++){
        a = GET_BYTE(b,i);
        indexOfArray = this->dataPtr / maxSizeEachArray;
        indexOfByte = this->dataPtr % maxSizeEachArray;
        c = this->source->at(indexOfArray).at(indexOfByte);
        (a == 1) ? SET_BYTE(c,7):CLR_BYTE(c,7);
        this->source->operator[](indexOfArray).operator[](indexOfByte) = c;
        this->targetData->append(c);
        this->dataPtr ++;
    }

}

void AnalyzeBmp::_init(){
    const char *infos = nullptr;
    RGBQUAD r;
    int ptr = 0;
    infos = source->at(0).constData();

    memcpy(&fileHeader, infos + ptr, sizeof (BITMAPFILEHEADER));
    ptr += sizeof (BITMAPFILEHEADER);
    memcpy(&infoHeader, infos + ptr, sizeof (BITMAPINFOHEADER));
    ptr += sizeof (BITMAPINFOHEADER);
    if(infoHeader.biBitCount == 24){         //24真彩
        this->quad = nullptr;
    }else{                                   //256色等
        memcpy(&r, infos + ptr, sizeof (RGBQUAD));
        this->quad = &r;
        ptr += sizeof (RGBQUAD);
    }
    this->dataPtr = fileHeader.bfOffBits;    
}

/*
此方法弃用
*/
//void AnalyzeBmp::_readBytes(){
//    int ListLen = list->getListLen();
////    int listSize = list->getListSize();
//    int maxSizeEachArray = list->getMaxSizeEachArray();
//    const char *infos = nullptr;

//    for(int i = 0; i< ListLen;i++){
//        if(i == 0){ //读取头文件
//            infos = list->at(i).constData();
//            int ptr = 0;
//            memcpy(&fileHeader, infos + ptr, sizeof (BITMAPFILEHEADER));
//            ptr += sizeof (BITMAPFILEHEADER);
//            memcpy(&infoHeader, infos + ptr, sizeof (BITMAPINFOHEADER));
//            ptr += sizeof (BITMAPINFOHEADER);
//            if(infoHeader.biBitCount == 24){         //24真彩
//                quad = nullptr;
//            }else{                                   //256色等
//                memcpy(quad, infos + ptr, sizeof (RGBQUAD));
//                ptr += sizeof (RGBQUAD);
//            }
//            dataPtr = ptr;
//        }else{

//        }
//        //        qDebug() << "quad is nullptr:" << (quad == nullptr);
//        //        qDebug() << infoHeader.biBitCount;
//        break;
//    }
//}

void AnalyzeBmp::setLSBtoZero(){
    //LSB清零
    for (int i = 0;i < this->getSourceList()->size();i++) {
        int head = (i != 0) ? 0:((this->getType_biBitCount() == 24) ? 54 : 58);
        for(int j=head;j < this->getSourceList()->at(i).size();j++){
            BYTE c = this->getSourceList()->operator[](i).operator[](j);
            c = (c >> 1) << 1;
            this->getSourceList()->operator[](i).operator[](j) = c;
        }

    }
}

void AnalyzeBmp::_clean(){
    if(source != nullptr){
        delete  source;
        source = nullptr;
    }
//    if(quad != nullptr){  //quad指针所对应的内容被c++直接管理，不需要手动释放内容
//        delete quad;
//        quad = nullptr;
//    }
    if(targetData != nullptr){
        delete targetData;
        targetData = nullptr;
    }


}
